package com.qiangesoft.bootcodegen.utils;

import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.CharUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.qiangesoft.bootcodegen.constant.CodegenConstant;
import com.qiangesoft.bootcodegen.constant.GenerationType;
import com.qiangesoft.bootcodegen.constant.HtmlType;
import com.qiangesoft.bootcodegen.entity.BcgColumnMap;
import com.qiangesoft.bootcodegen.entity.BcgProject;
import com.qiangesoft.bootcodegen.entity.BcgTable;
import com.qiangesoft.bootcodegen.entity.BcgTableColumn;
import com.qiangesoft.bootcodegen.pojo.bo.BcgTableBO;
import com.qiangesoft.bootcodegen.pojo.bo.BcgTableColumnBO;
import com.qiangesoft.bootcodegen.service.IBcgColumnMapService;
import com.qiangesoft.bootcodegen.service.IBcgProjectService;

import java.util.*;

/**
 * 代码生成工具类
 *
 * @author qiangesoft
 * @date 2024-03-29
 */
public class TableColumnInitUtil {

    /**
     * 下划线
     */
    public static final char UNDERLINE = '_';

    /**
     * 初始化表
     */
    public static BcgTable initTable(BcgTableBO tableBO) {
        BcgTable table = new BcgTable();
        String tableName = tableBO.getTableName();
        table.setTableName(tableName);
        table.setTableComment(tableBO.getTableComment());
        table.setGenFunction(tableBO.getTableComment());
        table.setGenModule(getFirstWord(tableName));
        table.setGenBusiness(getSecondWord(tableName));
        String camel = underlineToCamel(tableName);
        String genClass = camel.length() > 1 ? Character.toUpperCase(camel.charAt(0)) + camel.substring(1) : camel.toUpperCase();
        table.setGenClass(genClass);

        // 项目默认配置
        IBcgProjectService projectService = SpringUtil.getBean(IBcgProjectService.class);
        BcgProject project = projectService.getProject();
        if (project != null) {
            table.setGenAuthor(project.getProjectAuthor());
            table.setGenType(GenerationType.DIRECTORY.getCode());
            table.setGenPath(project.getProjectPath());
            table.setGenPackage(project.getProjectPackage());
        }
        return table;
    }

    /**
     * 初始化表字段
     */
    public static List<BcgTableColumn> initTableColumn(Long tableId, String dbType, List<BcgTableColumnBO> columnBOList) {
        IBcgColumnMapService columnMapService = SpringUtil.getBean(IBcgColumnMapService.class);
        List<BcgColumnMap> columnMapList = columnMapService.listColumnMapByDbType(dbType);
        Map<String, BcgColumnMap> columnMapMap = new HashMap<>();
        columnMapList.forEach(e -> columnMapMap.put(e.getColumnType(), e));

        List<BcgTableColumn> tableColumnList = new ArrayList<>();
        for (BcgTableColumnBO columnBO : columnBOList) {
            BcgTableColumn tableColumn = new BcgTableColumn();
            tableColumn.setTableId(tableId);
            tableColumn.setColumnName(columnBO.getColumnName());
            tableColumn.setColumnComment(columnBO.getColumnComment());
            tableColumn.setColumnType(columnBO.getColumnType());
            tableColumn.setColumnPk(columnBO.getColumnPk());
            tableColumn.setColumnNotNull(columnBO.getColumnNotNull());
            tableColumn.setColumnIncrement(columnBO.getColumnIncrement() != null && columnBO.getColumnIncrement());
            tableColumn.setJavaField(underlineToCamel(columnBO.getColumnName()));
            tableColumn.setPageForm(!columnBO.getColumnPk() && !arraysContains(CodegenConstant.NOT_DISPLAY_COLUMN, columnBO.getColumnName()));
            tableColumn.setPageFormRequired(!columnBO.getColumnPk() && columnBO.getColumnNotNull());
            tableColumn.setPageTableShow(!columnBO.getColumnPk() && !arraysContains(CodegenConstant.NOT_DISPLAY_COLUMN, columnBO.getColumnName()));
            tableColumn.setPageQuery(false);
            tableColumn.setPageQueryType(null);
            tableColumn.setPageHtmlType(HtmlType.INPUT.getKey());
            BcgColumnMap columnMap = columnMapMap.get(columnBO.getColumnType());
            if (columnMap != null) {
                tableColumn.setJavaType(columnMap.getJavaType());
                tableColumn.setJavaTypePackage(columnMap.getJavaTypePackage());
            } else {
                Optional<BcgColumnMap> first = columnMapList.stream().filter(e -> columnBO.getColumnType().contains(e.getColumnType())).findFirst();
                if (first.isPresent()) {
                    tableColumn.setJavaType(first.get().getJavaType());
                    tableColumn.setJavaTypePackage(first.get().getJavaTypePackage());
                } else {
                    tableColumn.setJavaType("String");
                    tableColumn.setJavaTypePackage("java.lang.String");
                }
            }
            tableColumnList.add(tableColumn);
        }
        return tableColumnList;
    }

    /**
     * 下划线转换驼峰
     */
    public static String underlineToCamel(String str) {
        if (null == str) {
            return null;
        }
        if (str.indexOf(UNDERLINE) == -1) {
            return str;
        }
        int length = str.length();
        StringBuilder sb = new StringBuilder(length);
        boolean upperCase = false;
        for (int i = 0; i < length; ++i) {
            char c = str.charAt(i);
            if (c == UNDERLINE) {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(Character.toLowerCase(c));
            }
        }
        return sb.toString();
    }

    /**
     * 驼峰转换连字符
     */
    public static String camelToChar(String str, char cr) {
        if (str == null) {
            return null;
        }
        int length = str.length();
        StrBuilder sb = new StrBuilder();
        for (int i = 0; i < length; ++i) {
            char c = str.charAt(i);
            if (Character.isUpperCase(c)) {
                Character preChar = i > 0 ? str.charAt(i - 1) : null;
                Character nextChar = i < str.length() - 1 ? str.charAt(i + 1) : null;
                if (null != preChar) {
                    if (cr == preChar) {
                        if (null == nextChar || Character.isLowerCase(nextChar)) {
                            c = Character.toLowerCase(c);
                        }
                    } else if (Character.isLowerCase(preChar)) {
                        sb.append(cr);
                        if (null == nextChar || Character.isLowerCase(nextChar) || CharUtil.isNumber(nextChar)) {
                            c = Character.toLowerCase(c);
                        }
                    } else if (null != nextChar && Character.isLowerCase(nextChar)) {
                        sb.append(cr);
                        c = Character.toLowerCase(c);
                    }
                } else if (null == nextChar || Character.isLowerCase(nextChar)) {
                    c = Character.toLowerCase(c);
                }
            }
            sb.append(c);
        }
        return sb.toString();
    }

    /**
     * 校验数组是否包含指定值
     *
     * @param array
     * @param value
     * @return
     */
    public static boolean arraysContains(String[] array, String value) {
        return Arrays.asList(array).contains(value);
    }

    /**
     * 获取第一个单词
     *
     * @param str
     * @return
     */
    public static String getFirstWord(String str) {
        int firstIndex = str.indexOf(UNDERLINE);
        if (firstIndex != -1) {
            return str.substring(0, firstIndex);
        }
        return str;
    }

    /**
     * 获取第二个单词
     *
     * @param str
     * @return
     */
    public static String getSecondWord(String str) {
        int firstIndex = str.indexOf(UNDERLINE);
        if (firstIndex == -1) {
            return null;
        }
        int nextIndex = firstIndex + 1;
        if (str.length() == nextIndex) {
            return null;
        }
        int secondIndex = str.indexOf(UNDERLINE, nextIndex);
        if (secondIndex == -1) {
            return str.substring(nextIndex);
        }
        return str.substring(nextIndex, secondIndex);
    }

    /**
     * 获取最后一个单词
     *
     * @param str
     * @return
     */
    public static String getLastWord(String str) {
        int lastIndex = str.lastIndexOf(UNDERLINE);
        if (lastIndex != -1) {
            return str.substring(lastIndex + 1);
        }
        return str;
    }
}
